home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume8 / hint / part01 next >
Encoding:
Text File  |  1989-08-24  |  42.7 KB  |  1,623 lines

  1. Newsgroups: comp.sources.misc
  2. From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  3. subject: v08i016: hint, an unobtrusive messager, part 1 of 2
  4. Reply-To: edf@ROCKY2.ROCKEFELLER.EDU (David MacKenzie)
  5.  
  6. Posting-number: Volume 8, Issue 16
  7. Submitted-by: edf@ROCKY2.ROCKEFELLER.EDU (David MacKenzie)
  8. Archive-name: hint/part01
  9.  
  10. hint is an alternative to write(1) that sends a one-line message to one
  11. or more other users.  The message appears along with the sender's user
  12. name and a beep (or, if possible, a ``visual bell'' such as flashing
  13. the screen) on the status line of the recipient's terminal, and
  14. disappears after 10 seconds.  If the recipient's terminal does not have
  15. a status line, hints appear wherever the cursor happens to be when they
  16. are received.
  17.  
  18.  
  19. #! /bin/sh
  20. # This is a shell archive.  Remove anything before this line, then unpack
  21. # it by saving it into a file and typing "sh file".  To overwrite existing
  22. # files, type "sh file -c".  You can also feed this as standard input via
  23. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  24. # will see the following message at the end:
  25. #        "End of archive 1 (of 2)."
  26. # Contents:  README hint.1 clearhint.1 hall.1 MANIFEST main.c hint.h
  27. #   hinttab.c hinttab.h stov.c stov.h str.c user.c hall.sh
  28. # Wrapped by dave@zedfdc on Thu Aug 24 19:49:21 1989
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. if test -f 'README' -a "${1}" != "-c" ; then 
  31.   echo shar: Will not clobber existing file \"'README'\"
  32. else
  33. echo shar: Extracting \"'README'\" \(1576 characters\)
  34. sed "s/^X//" >'README' <<'END_OF_FILE'
  35. XInstallation notes for hint
  36. X
  37. XTo allow people to disable write and talk messages but still allow
  38. Xhints, hint does not use the mesg bit to determine write permission.
  39. XInstead, it uses the group-execute bit of the tty. However, because
  40. Xsetting this bit does not actually give write permission, hint must run
  41. Xsetuid to root.  This ensures that running the hint program is the only
  42. Xinterface which can activate write permission for hints; that is
  43. Ximportant, because not only must the permission bit be set, but an
  44. Xentry in the file /usr/local/lib/hinttab must also be updated.
  45. X
  46. XA companion program, clearhint, is provided for systems where
  47. X"tput dsl" is not available to clear the status line.
  48. X
  49. XFor people with Wyse 50 terminals, the standard termcap files often don't
  50. Xhave the status line capabilities defined, and the Quick Reference Guide
  51. Xthat comes with the terminal isn't of much help either.  For a status
  52. Xline on the bottom, use:
  53. X    :hs:es:ds=\Ef\r:fs=\r:ts=\Ef:ws#78:
  54. X
  55. XFor a short status line on the top, use:
  56. X    :hs:es:ds=\EF \r:fs=\r:ts=\EF:ws#46:
  57. X
  58. XFor a flash instead of a beep (this works for vi also):
  59. X    :vb=\E`8\E`9:
  60. X
  61. XTerminfo users will need to adapt these.
  62. X
  63. XA brief history of hint is approximately as follows:
  64. X
  65. X-Originally written by Paul Borman, for the Heath/Zenith 29 terminal only.
  66. X-Rewritten by Mike Haertel, still for the H29 only.
  67. X-Simple terminal independence added by Walter Poxon and Jon Westbrock.
  68. X-Rewritten from scratch by David MacKenzie with an improved terminal
  69. X independence system and other enhancements.
  70. X
  71. XDavid MacKenzie <edf@rocky2.rockefeller.edu>
  72. END_OF_FILE
  73. if test 1576 -ne `wc -c <'README'`; then
  74.     echo shar: \"'README'\" unpacked with wrong size!
  75. fi
  76. # end of 'README'
  77. fi
  78. if test -f 'hint.1' -a "${1}" != "-c" ; then 
  79.   echo shar: Will not clobber existing file \"'hint.1'\"
  80. else
  81. echo shar: Extracting \"'hint.1'\" \(4553 characters\)
  82. sed "s/^X//" >'hint.1' <<'END_OF_FILE'
  83. X.\" Copyright (C) 1989 David MacKenzie
  84. X.\" 
  85. X.\" Permission is granted to make and distribute verbatim copies of this
  86. X.\" manual provided the copyright notice and this permission notice are
  87. X.\" preserved on all copies.
  88. X.\" 
  89. X.\" Permission is granted to process this file through nroff or troff
  90. X.\" and print the results.
  91. X.\"
  92. X.\" Permission is granted to copy and distribute modified versions of
  93. X.\" this manual under the conditions for verbatim copying, provided that
  94. X.\" the entire resulting derived work is distributed under the terms of
  95. X.\" a permission notice identical to this one.
  96. X.\" 
  97. X.\" Permission is granted to copy and distribute translations of this
  98. X.\" manual into another language, under the above conditions for
  99. X.\" modified versions.
  100. X.TH HINT 1L
  101. X.SH NAME
  102. Xhint \- send a one-line message to other users
  103. X.SH SYNOPSIS
  104. X\fBhint\fR [ \fB\-fp\fR ] [ \fB\-d sec\fR ]
  105. X\fBuser\fR|\fBtty\fR[\fB,user\fR|\fBtty\fR...] [ \fBmessage\fR ]
  106. X.br
  107. X\fBhint \-y\fR [ \fB\-bs\fR ] [ \fB\-T termtype\fR ]
  108. X.br
  109. X\fBhint \-n\fR
  110. X.br
  111. X\fBhint \-V\fR
  112. X.br
  113. X\fBhint\fR
  114. X.SH DESCRIPTION
  115. X.I hint
  116. Xsends a one-line message to one or more other users.  The message
  117. Xappears along with the sender's user name and a beep (or, if possible,
  118. Xa ``visual bell'' such as flashing the screen) on the status line of
  119. Xthe recipient's terminal, and disappears after 10 seconds.  If the
  120. Xrecipient's terminal does not have a status line, hints appear wherever
  121. Xthe cursor happens to be when they are received.
  122. X.PP
  123. XIf
  124. X.I hint
  125. Xis run with no arguments, it displays the user's current hint status,
  126. Xwhich is either
  127. X.B y
  128. Xor
  129. X.BR n ,
  130. Xmeaning the user is allowing or refusing hints, respectively.  The hint
  131. Xstatus is independent of the
  132. X.BR mesg (1)
  133. Xstatus.
  134. X.PP
  135. XIf one or more user names (e.g., \fIdave\fR)
  136. Xor terminal names (e.g., \fItty10\fR)
  137. Xare given (separated by commas but no spaces), any
  138. Xarguments after them are taken to be the message to send.  If
  139. Xthe message is not given on the command line,
  140. X.I hint
  141. Xprompts for the message from the keyboard.
  142. X.PP
  143. X.I hint
  144. Xsends the message to all terminals where each given user
  145. Xis logged on and all terminals given directly.
  146. X.I hint
  147. Xskips users who are not logged in and hint
  148. X.B y
  149. Xand terminals that are not hint
  150. X.BR y ,
  151. Xand sends the message to whatever users and terminals remain.
  152. X.SS OPTIONS
  153. X.PP
  154. XThe following options are used when setting the hint status:
  155. X.TP
  156. X.I \-y
  157. XAllow receipt of hints; no hint is sent.  This option saves the codes
  158. Xfor accessing your terminal's status line, as read from the
  159. X.BR termcap (5)
  160. Xor
  161. X.BR terminfo (4)
  162. Xdatabase (whichever is available),
  163. Xinto an entry in the file /usr/local/lib/hinttab.
  164. X.TP
  165. X.I \-b
  166. XForce hints that you receive to beep even if a ``visual bell'' is available.
  167. XHas no effect if the
  168. X.I \-y
  169. Xoption is not also given.
  170. X.TP
  171. X.I \-s
  172. XForce hints that you receive to be silent; a ``visual bell'' will be used
  173. Xif available.  If both
  174. X.I \-b
  175. Xand
  176. X.I \-s
  177. Xare given, neither a beep nor a ``visual bell'' will be used.
  178. XHas no effect if the
  179. X.I \-y
  180. Xoption is not also given.
  181. X.TP
  182. X.I \-T termtype
  183. XUse
  184. X.I termtype
  185. Xas the terminal type.
  186. XHas no effect if the
  187. X.I \-y
  188. Xoption is not also given.
  189. X.TP
  190. X.I \-n
  191. XRefuse receipt of hints; no hint is sent.
  192. X.PP
  193. XThe following options are used when sending a hint:
  194. X.TP
  195. X.I \-f
  196. XMake the hint last forever (until overwritten or cleared).  This option
  197. Xoverrides any
  198. X.I \-d
  199. Xoption given.
  200. X.TP
  201. X.I \-p
  202. XMake the sender's name appear preceding the hint, enclosed in parentheses,
  203. Xrather than after the hint, following a dash.
  204. X.TP
  205. X.I \-d sec
  206. XChange the hint duration from 10 seconds to
  207. X.I sec
  208. Xseconds.
  209. X.I sec
  210. Xis not allowed to be less than 5 or greater than 60.
  211. X.PP
  212. XAdditional options:
  213. X.TP
  214. X.I \-V
  215. XDisplay the version number of the
  216. X.I hint
  217. Xprogram; no other action is taken.
  218. X.SS ENVIRONMENT
  219. X.PP
  220. XAll options except
  221. X.IR \-y ,
  222. X.IR \-n ,
  223. Xand
  224. X.I -V
  225. Xcan be given defaults by setting the
  226. X.B HINT
  227. Xenvironment variable.
  228. XFor example, to change the default duration
  229. Xof hints that you send from 10 seconds to 15 seconds, and always
  230. Xreceive silent hints, you could use:
  231. X.sp
  232. X.RS
  233. XFor the C shell:
  234. X.br
  235. Xsetenv HINT "-d15 -s"
  236. X.sp
  237. XFor the Bourne and Korn shells:
  238. X.br
  239. XHINT="-d15 -s"; export HINT
  240. X.RE
  241. X.SH FILES
  242. X/usr/local/lib/hinttab
  243. X.SH "SEE ALSO"
  244. X.BR clearhint (1L),
  245. X.BR hall (1L),
  246. X.BR mesg (1),
  247. X.BR write (1),
  248. X.BR terminfo (4),
  249. X.BR termcap (5)
  250. X.SH BUGS
  251. XIf a hint is sent to several terminals which have different length
  252. Xstatus lines, the message will be truncated on all of the terminals to
  253. Xthe length of the shortest status line, so that everyone gets the same hint.
  254. X.PP
  255. XThere is no network support.
  256. X.SH AUTHOR
  257. XDavid MacKenzie
  258. END_OF_FILE
  259. if test 4553 -ne `wc -c <'hint.1'`; then
  260.     echo shar: \"'hint.1'\" unpacked with wrong size!
  261. fi
  262. # end of 'hint.1'
  263. fi
  264. if test -f 'clearhint.1' -a "${1}" != "-c" ; then 
  265.   echo shar: Will not clobber existing file \"'clearhint.1'\"
  266. else
  267. echo shar: Extracting \"'clearhint.1'\" \(1612 characters\)
  268. sed "s/^X//" >'clearhint.1' <<'END_OF_FILE'
  269. X.\" Copyright (C) 1989 David MacKenzie
  270. X.\" 
  271. X.\" Permission is granted to make and distribute verbatim copies of this
  272. X.\" manual provided the copyright notice and this permission notice are
  273. X.\" preserved on all copies.
  274. X.\" 
  275. X.\" Permission is granted to process this file through nroff or troff
  276. X.\" and print the results.
  277. X.\"
  278. X.\" Permission is granted to copy and distribute modified versions of
  279. X.\" this manual under the conditions for verbatim copying, provided that
  280. X.\" the entire resulting derived work is distributed under the terms of
  281. X.\" a permission notice identical to this one.
  282. X.\" 
  283. X.\" Permission is granted to copy and distribute translations of this
  284. X.\" manual into another language, under the above conditions for
  285. X.\" modified versions.
  286. X.TH CLEARHINT 1L
  287. X.SH NAME
  288. Xclearhint \- erase terminal's status line
  289. X.SH SYNOPSIS
  290. X.B clearhint
  291. X[
  292. X.B \-T terminal
  293. X]
  294. X.SH DESCRIPTION
  295. X.I clearhint
  296. Xerases the status
  297. Xline (usually a ``25th line'') of the user's terminal.  If the terminal
  298. Xdoes not have a status line,
  299. X.I clearhint
  300. Xdoes nothing.  The program
  301. Xis named for its main use, which is erasing messages sent by the
  302. X.BR hint (1L)
  303. Xprogram with the
  304. X.I \-f
  305. X(make the hint last forever) option given.
  306. X.PP
  307. X.I clearhint
  308. Xuses the
  309. X.BR termcap (5)
  310. Xor
  311. X.BR terminfo (4)
  312. Xdatabase (whichever is available) to determine how to move the cursor to the
  313. Xstatus line of each user's terminal.
  314. X.SS OPTIONS
  315. X.TP
  316. X.I \-T terminal
  317. XUse
  318. X.I terminal
  319. Xas the terminal type instead of the value given by the
  320. X.B TERM
  321. Xenvironment variable.
  322. X.SH "SEE ALSO"
  323. X.BR hall (1L),
  324. X.BR hint (1L),
  325. X.BR terminfo (4),
  326. X.BR termcap (5)
  327. X.SH AUTHOR
  328. XDavid MacKenzie
  329. END_OF_FILE
  330. if test 1612 -ne `wc -c <'clearhint.1'`; then
  331.     echo shar: \"'clearhint.1'\" unpacked with wrong size!
  332. fi
  333. # end of 'clearhint.1'
  334. fi
  335. if test -f 'hall.1' -a "${1}" != "-c" ; then 
  336.   echo shar: Will not clobber existing file \"'hall.1'\"
  337. else
  338. echo shar: Extracting \"'hall.1'\" \(1161 characters\)
  339. sed "s/^X//" >'hall.1' <<'END_OF_FILE'
  340. X.\" Copyright (C) 1989 David MacKenzie
  341. X.\" 
  342. X.\" Permission is granted to make and distribute verbatim copies of this
  343. X.\" manual provided the copyright notice and this permission notice are
  344. X.\" preserved on all copies.
  345. X.\" 
  346. X.\" Permission is granted to process this file through nroff or troff
  347. X.\" and print the results.
  348. X.\"
  349. X.\" Permission is granted to copy and distribute modified versions of
  350. X.\" this manual under the conditions for verbatim copying, provided that
  351. X.\" the entire resulting derived work is distributed under the terms of
  352. X.\" a permission notice identical to this one.
  353. X.\" 
  354. X.\" Permission is granted to copy and distribute translations of this
  355. X.\" manual into another language, under the above conditions for
  356. X.\" modified versions.
  357. X.TH HALL 1L
  358. X.SH NAME
  359. Xhall - hint all users logged on
  360. X.SH SYNOPSIS
  361. X.B hall
  362. X[
  363. X.B message
  364. X]
  365. X.SH DESCRIPTION
  366. X.I hall
  367. Xsends a hint message to everyone who is logged on to the
  368. Xmachine where it is run and who is hint
  369. X.BR y .
  370. XIf no message is given on the command line,
  371. X.I hall
  372. Xprompts for one.
  373. X.SH FILES
  374. X.TP
  375. X/etc/utmp
  376. Xlist of who is logged on
  377. X.SH "SEE ALSO"
  378. X.BR clearhint (1L),
  379. X.BR hint (1L)
  380. X.SH AUTHOR
  381. XDavid MacKenzie
  382. END_OF_FILE
  383. if test 1161 -ne `wc -c <'hall.1'`; then
  384.     echo shar: \"'hall.1'\" unpacked with wrong size!
  385. fi
  386. # end of 'hall.1'
  387. fi
  388. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  389.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  390. else
  391. echo shar: Extracting \"'MANIFEST'\" \(672 characters\)
  392. sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  393. X   File Name        Archive #    Description
  394. X-----------------------------------------------------------
  395. X README                     1    
  396. X hint.1                     1    
  397. X clearhint.1                1    
  398. X hall.1                     1    
  399. X MANIFEST                   1    This shipping list
  400. X main.c                     1    
  401. X hint.h                     1    
  402. X hinttab.c                  1    
  403. X hinttab.h                  1    
  404. X stov.c                     1    
  405. X stov.h                     1    
  406. X str.c                      1    
  407. X tty.c                      2    
  408. X user.c                     1    
  409. X clearhint.c                2    
  410. X hall.sh                    1    
  411. X Makefile                   2    
  412. X COPYING                    2    
  413. END_OF_FILE
  414. if test 672 -ne `wc -c <'MANIFEST'`; then
  415.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  416. fi
  417. # end of 'MANIFEST'
  418. fi
  419. if test -f 'main.c' -a "${1}" != "-c" ; then 
  420.   echo shar: Will not clobber existing file \"'main.c'\"
  421. else
  422. echo shar: Extracting \"'main.c'\" \(10862 characters\)
  423. sed "s/^X//" >'main.c' <<'END_OF_FILE'
  424. X/* main.c -- argument parser and control loops
  425. X   Copyright (C) 1989 David MacKenzie
  426. X
  427. X   This program is free software; you can redistribute it and/or modify
  428. X   it under the terms of the GNU General Public License as published by
  429. X   the Free Software Foundation; either version 1, or (at your option)
  430. X   any later version.
  431. X
  432. X   This program is distributed in the hope that it will be useful,
  433. X   but WITHOUT ANY WARRANTY; without even the implied warranty of
  434. X   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  435. X   GNU General Public License for more details.
  436. X
  437. X   You should have received a copy of the GNU General Public License
  438. X   along with this program; if not, write to the Free Software
  439. X   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  440. X
  441. X/* hint - send a one-line message to other users
  442. X
  443. X   Usage: hint [-fp] [-d sec] user|tty[,user|tty...] [message]
  444. X      hint -y [-bs] [-T terminal]
  445. X      hint -n
  446. X      hint -V
  447. X      hint
  448. X
  449. X   Options:
  450. X   -f    make hint last forever, until overwritten
  451. X   -p    put sender's name at beginning of hint instead of end
  452. X   -d    duration in seconds (5 <= sec <= 60) before hint is erased (default 10)
  453. X
  454. X   -y    enable receipt of hints
  455. X   -b    don't use a visual bell (can still use audible bell)
  456. X   -s    don't use an audible bell (can still use visual bell)
  457. X   -T    specify terminal type, overriding $TERM
  458. X
  459. X   -n    disable receipt of hints
  460. X
  461. X   -V    display program version number
  462. X
  463. X   With no arguments, displays the current hint status.
  464. X
  465. X   David MacKenzie <edf@rocky2.rockefeller.edu>
  466. X   Latest revision: 08/24/89 */
  467. X
  468. X#define ALLOCATE        /* Allocate global variables in hint.h. */
  469. X
  470. X#include "hint.h"
  471. X
  472. X/* Hint status to set if 'y' or 'n'. */
  473. Xstatic int new_stats;
  474. X
  475. X/* The hint message can be no longer than this. */
  476. Xstatic int length_limit;
  477. X
  478. X/* Head of linked list of ttys to hint. */
  479. Xstatic struct ttylist *tty_list;
  480. X
  481. Xint
  482. Xmain (argc, argv)
  483. X     int argc;
  484. X     char **argv;
  485. X{
  486. X  extern int optind;
  487. X  struct ttylist *tp;        /* A ttylist entry. */
  488. X  char temp_message[MAX_MESSAGE];    /* Hint read from tty. */
  489. X  int i;            /* To reset `optind' between uses. */
  490. X
  491. X  program_name = argv[0] = basename (argv[0]);
  492. X  new_stats = 0;
  493. X  length_limit = MAX_MESSAGE - 1;
  494. X
  495. X  if (argc == 1)
  496. X    {
  497. X      show_status ();
  498. X      exit (0);
  499. X    }
  500. X
  501. X  if (chdir ("/dev") == -1)
  502. X    pfatal ("Cannot change directory to /dev");
  503. X
  504. X  term = getenv ("TERM");
  505. X  /* Some implementations of getopt seem to start out with `optind' == 0,
  506. X     while others start out with `optind' == 1.  Whatever it starts out as,
  507. X     we save it and then restore it.  */
  508. X  i = optind;
  509. X  parse_environment ();
  510. X  optind = i;
  511. X  parse_options (argc, argv, 1);
  512. X
  513. X  if (new_stats)
  514. X    {
  515. X      if (argc < optind)
  516. X    usage ();
  517. X      set_status (new_stats);
  518. X      exit (0);
  519. X    }
  520. X
  521. X  /* Check for user|tty[,user|tty...]. */
  522. X  if (optind < argc)
  523. X      add_recipients (argv[optind++]);
  524. X  if (tty_list == NULL)
  525. X    {
  526. X      fprintf (stderr, "%s: No ttys to hint\n", program_name);
  527. X      exit (1);
  528. X    }
  529. X  endhtent ();
  530. X
  531. X  length_limit -= 11;        /* 8 for username + 3 for punctuation. */
  532. X  if (length_limit < 11)
  533. X    length_limit = 11;        /* Let's be reasonable. */
  534. X
  535. X  /* Check for message. */
  536. X  if (optind < argc)
  537. X    for (; optind < argc; ++optind)
  538. X      {
  539. X    append_word (argv[optind]);
  540. X    if (optind < argc - 1)
  541. X      append_word (" ");
  542. X      }
  543. X  else
  544. X    {
  545. X      prompt ();
  546. X      fgets (temp_message, MAX_MESSAGE, stdin);
  547. X      append_word (temp_message);
  548. X    }
  549. X
  550. X  set_signals ();
  551. X  /* Send the hint to all relevant ttys. */
  552. X  while (tp = next_tty ())
  553. X    sendhint (tp);
  554. X
  555. X  if (forever)
  556. X    exit (0);
  557. X  switch (fork ())
  558. X    {
  559. X    case -1:
  560. X      pfatal ("Cannot fork");
  561. X    case 0:            /* Child. */
  562. X      sleep (duration);
  563. X      while (tp = next_tty ())
  564. X    erasehint (tp);
  565. X    }
  566. X  exit (0);
  567. X  /* NOTREACHED */
  568. X}
  569. X
  570. Xvoid
  571. Xparse_environment ()
  572. X{
  573. X  char *enval;
  574. X  struct args *argsp;
  575. X  char *s;            /* program_name + enval. */
  576. X
  577. X  enval = getenv (ENVAR);
  578. X  if (enval && *enval)
  579. X    {
  580. X      s = xmalloc ((unsigned) (strlen (enval) + strlen (program_name) + 2));
  581. X      strcpy (s, program_name);
  582. X      strcat (s, " ");
  583. X      strcat (s, enval);
  584. X      argsp = stov (s);
  585. X      parse_options (argsp->argc, argsp->argv, 0);
  586. X      free (s);
  587. X    }
  588. X}
  589. X
  590. X/* If `cmdline' is nonzero, this function was called with command line
  591. X   arguments; otherwise they were taken from the environment. */
  592. X
  593. Xvoid
  594. Xparse_options (argc, argv, cmdline)
  595. X     int argc;
  596. X     char **argv;
  597. X     int cmdline;
  598. X{
  599. X  extern int optind;
  600. X  extern char *optarg;
  601. X  int c;
  602. X
  603. X  while ((c = getopt (argc, argv, "ynbfpsd:T:V")) != EOF)
  604. X    {
  605. X      switch (c)
  606. X    {
  607. X    case 'y':
  608. X    case 'n':
  609. X      if (cmdline)
  610. X        new_stats = c;
  611. X      else
  612. X        ignored (c);
  613. X      break;
  614. X    case 'b':
  615. X      use_vbell = 0;
  616. X      break;
  617. X    case 'f':
  618. X      forever = 1;
  619. X      break;
  620. X    case 'p':
  621. X      name_at_end = 0;
  622. X      break;
  623. X    case 's':
  624. X      use_bell = 0;
  625. X      break;
  626. X    case 'd':
  627. X      duration = atoi (optarg);
  628. X      if (duration < MIN_SEC || duration > MAX_SEC)
  629. X        {
  630. X          fprintf (stderr,
  631. X               "%s: %d: Duration out of range (%d-%d seconds)\n",
  632. X               program_name, duration, MIN_SEC, MAX_SEC);
  633. X          exit (1);
  634. X        }
  635. X      break;
  636. X    case 'T':
  637. X      term = optarg;
  638. X      break;
  639. X    case 'V':
  640. X      if (cmdline)
  641. X        {
  642. X          fprintf (stderr, "hint, version 3.5\n");
  643. X          exit (0);
  644. X        }
  645. X      else
  646. X        ignored (c);
  647. X      break;
  648. X    default:
  649. X      if (cmdline)
  650. X        usage ();
  651. X      else
  652. X        fprintf (stderr, "%s: Invalid option in environment ignored\n",
  653. X             program_name);
  654. X      break;
  655. X    }
  656. X    }
  657. X}
  658. X
  659. X/* Display a prompt that attempts to be as long as `length_limit'. */
  660. X
  661. Xvoid
  662. Xprompt ()
  663. X{
  664. X  static char *prompt_string = "[ Enter message (max. %d characters):";
  665. X  int prompt_length;
  666. X
  667. X  printf (prompt_string, length_limit);
  668. X  /* Set prompt_length to length of the prompt except for trailing spaces. */
  669. X  prompt_length = strlen (prompt_string) + 1;    /* The 1 is the ']'. */
  670. X  if (length_limit > 99)
  671. X    ++prompt_length;        /* Adjust for the extra digit. */
  672. X  if (prompt_length > length_limit)
  673. X    prompt_length = length_limit;
  674. X  printf ("%*s]\n", length_limit - prompt_length, " ");
  675. X  fflush (stdout);
  676. X}
  677. X
  678. X/* Print the program name, `s', and a system error message, and die.  */
  679. X
  680. Xvoid
  681. Xpfatal (s)
  682. X     char *s;
  683. X{
  684. X  fprintf (stderr, "%s: ", program_name);
  685. X  perror (s);
  686. X  exit (1);
  687. X}
  688. X
  689. X/* Same but stay alive. */
  690. X
  691. Xvoid
  692. Xpnonfatal (s)
  693. X     char *s;
  694. X{
  695. X  fprintf (stderr, "%s: ", program_name);
  696. X  perror (s);
  697. X}
  698. X
  699. Xvoid
  700. Xshow_status ()
  701. X{
  702. X  char *tty;
  703. X
  704. X  tty = ttyname (2);        /* Stderr is least likely to be redirected. */
  705. X  if (tty == NULL)
  706. X    pfatal ("Cannot get ttyname");
  707. X  printf ("is %c\n", hintable (tty) ? 'y' : 'n');
  708. X}
  709. X
  710. X/* Set hint status.
  711. X   `newstat' can be 'y' or 'n'.  */
  712. X
  713. Xvoid
  714. Xset_status (newstat)
  715. X     char newstat;
  716. X{
  717. X  struct stat tty_stats;
  718. X  char *tty;
  719. X
  720. X  tty = ttyname (2);
  721. X  if (tty == NULL)
  722. X    pfatal ("Cannot get ttyname");
  723. X  if (stat (tty, &tty_stats) < 0)
  724. X    pfatal (tty);
  725. X
  726. X  if (newstat == 'y')
  727. X    {
  728. X      tty_stats.st_mode |= HINTBIT;
  729. X      updatetab (tty);
  730. X    }
  731. X  else
  732. X    tty_stats.st_mode &= ~HINTBIT;
  733. X  if (chmod (tty, tty_stats.st_mode) < 0)
  734. X    pfatal (tty);
  735. X}
  736. X
  737. X/* Return true if `tty' is hint y, false otherwise.  */
  738. X
  739. Xint
  740. Xhintable (tty)
  741. X     char *tty;
  742. X{
  743. X  struct stat tty_stats;
  744. X
  745. X  if (stat (tty, &tty_stats) < 0)
  746. X    {
  747. X      pnonfatal (tty);
  748. X      return 0;            /* Cannot stat; assume they're hint n. */
  749. X    }
  750. X  return tty_stats.st_mode & HINTBIT;
  751. X}
  752. X
  753. X/* Return true if `name' is a tty device in /dev. */
  754. X
  755. Xint
  756. Xistty (name)
  757. X     char *name;
  758. X{
  759. X  struct stat stats;
  760. X  char *path;
  761. X  int i;
  762. X
  763. X  path = xmalloc (strlen (name) + 3);
  764. X  strcpy (path, "./");
  765. X  strcat (path, name);
  766. X  i = stat (path, &stats);
  767. X  free (path);
  768. X  if (i == -1 || (stats.st_mode & S_IFMT) != S_IFCHR)
  769. X    return 0;
  770. X  else
  771. X    return 1;
  772. X}
  773. X
  774. Xvoid
  775. Xadd_recipients (names)
  776. X     char *names;
  777. X{
  778. X  char *name;
  779. X
  780. X  for (name = strtok (names, ","); name; name = strtok ((char *) NULL, ","))
  781. X    if (istty (name))
  782. X      {
  783. X    addtty ("user", name);
  784. X      }
  785. X    else
  786. X      {
  787. X    /* Add any ttys where user `name' is logged on to `tty_list'. */
  788. X    if (adduser (name) == 0)
  789. X      fprintf (stderr, "%s: %s is not logged on\n", program_name, name);
  790. X      }
  791. X}
  792. X
  793. X/* Add `user' at `tty' (which should have no leading path) to the list of
  794. X   ttys to send the hint to.  */
  795. X
  796. Xvoid
  797. Xaddtty (user, tty)
  798. X     char *user;
  799. X     char *tty;
  800. X{
  801. X  struct ttylist *tp;
  802. X  struct hinttab *ht;
  803. X  char *ttypath;
  804. X
  805. X  /* Make sure they haven't already been added. */
  806. X  for (tp = tty_list; tp; tp = tp->tt_next)
  807. X    if (!strcmp (tp->tt_tty, tty))
  808. X      return;
  809. X
  810. X  if (!hintable (tty))
  811. X    {
  812. X      /* They're hint n. */
  813. X      fprintf (stderr, "%s: %s on %s is refusing hints\n",
  814. X           program_name, user, tty);
  815. X      return;
  816. X    }
  817. X
  818. X  sethtent ();            /* Rewind hinttab file. */
  819. X
  820. X  ttypath = xmalloc ((unsigned) (strlen (tty) + 6));
  821. X  strcpy (ttypath, "/dev/");
  822. X  strcat (ttypath, tty);
  823. X  ht = gethttty (ttypath);
  824. X  free (ttypath);
  825. X
  826. X  if (ht == NULL)
  827. X    {
  828. X      fprintf (stderr, "%s: No hinttab entry for %s\n", program_name, tty);
  829. X      return;
  830. X    }
  831. X
  832. X  tp = (struct ttylist *) xmalloc (sizeof (struct ttylist));
  833. X  tp->tt_user = strdup (user);
  834. X  tp->tt_tty = strdup (tty);
  835. X  tp->tt_ht = *ht;
  836. X
  837. X  tp->tt_next = tty_list;
  838. X  tty_list = tp;
  839. X
  840. X  /* Keep track of the shortest status line we'll be hinting. */
  841. X  if (length_limit > tp->tt_ht.h_ws)
  842. X    length_limit = tp->tt_ht.h_ws;
  843. X}
  844. X
  845. X/* Return the next tty in the list.
  846. X   Return NULL if the list is empty.  */
  847. X
  848. Xstruct ttylist *
  849. Xnext_tty ()
  850. X{
  851. X  static struct ttylist *tp = NULL;
  852. X
  853. X  tp = tp ? tp->tt_next : tty_list;
  854. X
  855. X  return tp;
  856. X}
  857. X
  858. Xvoid
  859. Xset_signals ()
  860. X{
  861. X#ifdef SIGTTOU
  862. X  signal (SIGTTOU, SIG_IGN);
  863. X#endif
  864. X  /* If the sender logs out right after hinting, stick around to erase the
  865. X     hint. */
  866. X  signal (SIGHUP, SIG_IGN);
  867. X  signal (SIGINT, SIG_IGN);
  868. X}
  869. X
  870. X/* Concatenate `word' onto the end of the hint message, silently truncating
  871. X   if it would overflow `length_limit', and removing any control
  872. X   characters.  */
  873. X
  874. Xvoid
  875. Xappend_word (word)
  876. X     char *word;
  877. X{
  878. X  static int message_length = 0;/* Length of message. */
  879. X
  880. X  for (; *word && message_length < length_limit; ++word)
  881. X    if (isascii (*word) && isprint (*word))
  882. X      message[message_length++] = *word;
  883. X  message[message_length] = 0;
  884. X}
  885. X
  886. X/* Return a malloc'd duplicate of string `s'. */
  887. X
  888. Xchar *
  889. Xstrdup (s)
  890. X     char *s;
  891. X{
  892. X  return strcpy (xmalloc ((unsigned) (strlen (s) + 1)), s);
  893. X}
  894. X
  895. X/* Return `name' with any leading path stripped off.  */
  896. X
  897. Xchar *
  898. Xbasename (name)
  899. X     char *name;
  900. X{
  901. X  char *base;
  902. X
  903. X  base = strrchr (name, '/');
  904. X  return base ? base + 1 : name;
  905. X}
  906. X
  907. Xvoid
  908. Xignored (c)
  909. X     char c;
  910. X{
  911. X  fprintf (stderr, "%s: Option ignored in environment: -%c\n", program_name, c);
  912. X}
  913. X
  914. Xvoid
  915. Xusage ()
  916. X{
  917. X  fprintf (stderr,
  918. X       "Usage: %s [-fp] [-d sec] user|tty[,user|tty...] [message]\n",
  919. X       program_name);
  920. X  fprintf (stderr, "       %s -y [-bs] [-T termtype]\n", program_name);
  921. X  fprintf (stderr, "       %s -n\n", program_name);
  922. X  fprintf (stderr, "       %s -V\n", program_name);
  923. X  fprintf (stderr, "       %s\n", program_name);
  924. X  exit (1);
  925. X}
  926. END_OF_FILE
  927. if test 10862 -ne `wc -c <'main.c'`; then
  928.     echo shar: \"'main.c'\" unpacked with wrong size!
  929. fi
  930. # end of 'main.c'
  931. fi
  932. if test -f 'hint.h' -a "${1}" != "-c" ; then 
  933.   echo shar: Will not clobber existing file \"'hint.h'\"
  934. else
  935. echo shar: Extracting \"'hint.h'\" \(3447 characters\)
  936. sed "s/^X//" >'hint.h' <<'END_OF_FILE'
  937. X/* hint.h -- constant, variable and function declarations
  938. X   Copyright (C) 1989 David MacKenzie
  939. X
  940. X   This program is free software; you can redistribute it and/or modify
  941. X   it under the terms of the GNU General Public License as published by
  942. X   the Free Software Foundation; either version 1, or (at your option)
  943. X   any later version.
  944. X
  945. X   This program is distributed in the hope that it will be useful,
  946. X   but WITHOUT ANY WARRANTY; without even the implied warranty of
  947. X   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  948. X   GNU General Public License for more details.
  949. X
  950. X   You should have received a copy of the GNU General Public License
  951. X   along with this program; if not, write to the Free Software
  952. X   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  953. X
  954. X#ifndef USG
  955. X#define strrchr rindex
  956. X#endif
  957. X
  958. X/* Enforced limits on hint duration. */
  959. X#define MIN_SEC 5
  960. X#define MAX_SEC 60
  961. X
  962. X/* Maximum length of message (who has terminals wider than this?). */
  963. X#define MAX_MESSAGE 400
  964. X
  965. X/* Default status line width if not defined in termcap. */
  966. X#define DEF_WS 78
  967. X
  968. X/* The bit that determines hint y or n. */
  969. X#define HINTBIT 00010
  970. X
  971. X/* Environment variable to check for options. */
  972. X#define ENVAR "HINT"
  973. X
  974. X#include <stdio.h>
  975. X#include <sys/types.h>
  976. X#include <sys/stat.h>
  977. X#include <ctype.h>
  978. X#include <pwd.h>
  979. X#include <fcntl.h>
  980. X#include <signal.h>
  981. X#ifdef USG
  982. X#include <termio.h>
  983. X#else
  984. X#include <sgtty.h>
  985. X#endif
  986. X
  987. X#include "stov.h"
  988. X#include "hinttab.h"
  989. X
  990. X/* List of ttys to send hint to. */
  991. Xstruct ttylist
  992. X{
  993. X  char *tt_user;
  994. X  char *tt_tty;            /* Contains no leading path. */
  995. X  struct hinttab tt_ht;
  996. X  struct ttylist *tt_next;
  997. X};
  998. X
  999. X#ifdef ALLOCATE
  1000. X#define EXTERN
  1001. X#define INIT(x) = {x}
  1002. X#else
  1003. X#define EXTERN extern
  1004. X#define INIT(x)
  1005. X#endif
  1006. X
  1007. X/* Base of the name this program was run with. */
  1008. XEXTERN char *program_name;
  1009. X
  1010. X/* Terminal type. */
  1011. XEXTERN char *term;
  1012. X
  1013. X/* The hint to send. */
  1014. XEXTERN char message[MAX_MESSAGE];
  1015. X
  1016. X/* If nonzero, put the name at the start of the hint. */
  1017. XEXTERN int name_at_end INIT (1);
  1018. X
  1019. X/* If nonzero, erase the hint. */
  1020. XEXTERN int forever INIT (0);
  1021. X
  1022. X/* If nonzero, try to use bell capability. */
  1023. XEXTERN int use_bell INIT (1);
  1024. X
  1025. X/* If nonzero, try to use visual bell capability. */
  1026. XEXTERN int use_vbell INIT (1);
  1027. X
  1028. X/* Seconds between sending the hint and erasing it. */
  1029. XEXTERN int duration INIT (10);
  1030. X
  1031. Xchar *getenv ();
  1032. Xchar *getlogin ();
  1033. Xchar *malloc ();
  1034. Xchar *realloc ();
  1035. Xchar *strcat ();
  1036. Xchar *strcpy ();
  1037. Xchar *strncat ();
  1038. Xchar *strncpy ();
  1039. Xchar *strrchr ();
  1040. Xchar *strtok ();
  1041. Xchar *tgetstr ();
  1042. Xchar *tgoto ();
  1043. Xchar *ttyname ();
  1044. Xint strcspn ();
  1045. Xint strspn ();
  1046. Xoff_t lseek ();
  1047. Xstruct passwd *getpwuid ();
  1048. Xunsigned sleep ();
  1049. Xvoid perror ();
  1050. Xvoid exit ();
  1051. Xvoid free ();
  1052. X
  1053. Xchar *basename ();
  1054. Xchar *pwname ();
  1055. Xchar *strdup ();
  1056. Xchar *whoami ();
  1057. Xchar *xmalloc ();
  1058. Xchar *xrealloc ();
  1059. Xint addmatch ();
  1060. Xint adduser ();
  1061. Xint buffer_char ();
  1062. Xint hintable ();
  1063. Xint istty ();
  1064. Xstruct args *stov ();
  1065. Xstruct hinttab *gethttty ();
  1066. Xstruct ttylist *next_tty ();
  1067. Xvoid add_recipients ();
  1068. Xvoid addtty ();
  1069. Xvoid append_word ();
  1070. Xvoid buffer_string ();
  1071. Xvoid endhtent ();
  1072. Xvoid erasehint ();
  1073. Xvoid flush_buffer ();
  1074. Xvoid get_speed ();
  1075. Xvoid ignored ();
  1076. Xvoid init_buffer ();
  1077. Xvoid parse_environment ();
  1078. Xvoid parse_options ();
  1079. Xvoid pfatal ();
  1080. Xvoid pnonfatal ();
  1081. Xvoid prompt ();
  1082. Xvoid sendhint ();
  1083. Xvoid set_signals ();
  1084. Xvoid set_status ();
  1085. Xvoid sethtapp ();
  1086. Xvoid sethtent ();
  1087. Xvoid setup_termcap ();
  1088. Xvoid show_status ();
  1089. Xvoid updatetab ();
  1090. Xvoid usage ();
  1091. Xvoid writehtent ();
  1092. END_OF_FILE
  1093. if test 3447 -ne `wc -c <'hint.h'`; then
  1094.     echo shar: \"'hint.h'\" unpacked with wrong size!
  1095. fi
  1096. # end of 'hint.h'
  1097. fi
  1098. if test -f 'hinttab.c' -a "${1}" != "-c" ; then 
  1099.   echo shar: Will not clobber existing file \"'hinttab.c'\"
  1100. else
  1101. echo shar: Extracting \"'hinttab.c'\" \(2073 characters\)
  1102. sed "s/^X//" >'hinttab.c' <<'END_OF_FILE'
  1103. X/* hinttab.c -- functions for dealing with hinttab
  1104. X   Copyright (C) 1989 David MacKenzie
  1105. X
  1106. X   This program is free software; you can redistribute it and/or modify
  1107. X   it under the terms of the GNU General Public License as published by
  1108. X   the Free Software Foundation; either version 1, or (at your option)
  1109. X   any later version.
  1110. X
  1111. X   This program is distributed in the hope that it will be useful,
  1112. X   but WITHOUT ANY WARRANTY; without even the implied warranty of
  1113. X   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1114. X   GNU General Public License for more details.
  1115. X
  1116. X   You should have received a copy of the GNU General Public License
  1117. X   along with this program; if not, write to the Free Software
  1118. X   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  1119. X
  1120. X#include "hint.h"
  1121. X
  1122. Xstatic int fd = -1;
  1123. Xstatic off_t offset;
  1124. X
  1125. X/* Open (rewind if already open) the hinttab for reading and writing.  */
  1126. X
  1127. Xvoid
  1128. Xsethtent ()
  1129. X{
  1130. X  if (fd == -1)
  1131. X    {
  1132. X      fd = open (HINTTAB, O_RDWR);
  1133. X      if (fd == -1)
  1134. X    pfatal (HINTTAB);
  1135. X    }
  1136. X  else
  1137. X    {
  1138. X      offset = 0;
  1139. X      if (lseek (fd, offset, 0) == -1)
  1140. X    pfatal (HINTTAB);
  1141. X    }
  1142. X}
  1143. X
  1144. X/* Open the hinttab for appending.  */
  1145. X
  1146. Xvoid
  1147. Xsethtapp ()
  1148. X{
  1149. X  if (fd != -1)
  1150. X    close (fd);
  1151. X  fd = open (HINTTAB, O_WRONLY | O_APPEND);
  1152. X  if (fd == -1)
  1153. X    pfatal (HINTTAB);
  1154. X  offset = 0;
  1155. X}
  1156. X
  1157. X/* Return a pointer to the hinttab entry matching `tty', or
  1158. X   NULL if none do.
  1159. X   The offset into hinttab will be left pointing to the start of the
  1160. X   matching entry. */
  1161. X
  1162. Xstruct hinttab *
  1163. Xgethttty (tty)
  1164. X     char *tty;
  1165. X{
  1166. X  static struct hinttab h;
  1167. X
  1168. X  while (offset = lseek (fd, (off_t) 0, 1),
  1169. X     read (fd, &h, sizeof (h)) == sizeof (h))
  1170. X    {
  1171. X      if (!strcmp (tty, h.h_tty))
  1172. X    {
  1173. X      /* Seek back to the start of the record. */
  1174. X      lseek (fd, offset, 0);
  1175. X      return &h;
  1176. X    }
  1177. X    }
  1178. X  return NULL;
  1179. X}
  1180. X
  1181. X/* Update the current entry (the last one matched by gethttty).  */
  1182. X
  1183. Xvoid
  1184. Xwritehtent (h)
  1185. X     struct hinttab *h;
  1186. X{
  1187. X  if (write (fd, h, sizeof (*h)) != sizeof (*h))
  1188. X    pfatal (HINTTAB);
  1189. X}
  1190. X
  1191. X/* Close the hinttab.  */
  1192. X
  1193. Xvoid
  1194. Xendhtent ()
  1195. X{
  1196. X  close (fd);
  1197. X  fd = -1;
  1198. X}
  1199. END_OF_FILE
  1200. if test 2073 -ne `wc -c <'hinttab.c'`; then
  1201.     echo shar: \"'hinttab.c'\" unpacked with wrong size!
  1202. fi
  1203. # end of 'hinttab.c'
  1204. fi
  1205. if test -f 'hinttab.h' -a "${1}" != "-c" ; then 
  1206.   echo shar: Will not clobber existing file \"'hinttab.h'\"
  1207. else
  1208. echo shar: Extracting \"'hinttab.h'\" \(1411 characters\)
  1209. sed "s/^X//" >'hinttab.h' <<'END_OF_FILE'
  1210. X/* hinttab.h -- declarations for accessing the hinttab file
  1211. X   Copyright (C) 1989 David MacKenzie
  1212. X
  1213. X   This program is free software; you can redistribute it and/or modify
  1214. X   it under the terms of the GNU General Public License as published by
  1215. X   the Free Software Foundation; either version 1, or (at your option)
  1216. X   any later version.
  1217. X
  1218. X   This program is distributed in the hope that it will be useful,
  1219. X   but WITHOUT ANY WARRANTY; without even the implied warranty of
  1220. X   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1221. X   GNU General Public License for more details.
  1222. X
  1223. X   You should have received a copy of the GNU General Public License
  1224. X   along with this program; if not, write to the Free Software
  1225. X   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  1226. X
  1227. X/* Maximum length of termcap strings. */
  1228. X#define TCSLEN 20
  1229. X
  1230. X/* Structure of record in hinttab.
  1231. X   These are the strings returned by tgetstr.  They will be run through
  1232. X   tputs when the hint is actually sent.
  1233. X
  1234. X   Records are assigned in hinttab in first come, first served order.  */
  1235. Xstruct hinttab
  1236. X{
  1237. X  char h_tty[15];        /* Full pathname. */
  1238. X  char h_ts[TCSLEN];        /* Go to status line. */
  1239. X  char h_fs[TCSLEN];        /* Go from status line. */
  1240. X  char h_ds[TCSLEN];        /* Disable (clear) status line. */
  1241. X  char h_bl[TCSLEN];        /* Bell or visible bell. */
  1242. X  short h_ws;            /* Width (columns) of status line. */
  1243. X};
  1244. X
  1245. Xstruct hinttab *gethttty ();
  1246. END_OF_FILE
  1247. if test 1411 -ne `wc -c <'hinttab.h'`; then
  1248.     echo shar: \"'hinttab.h'\" unpacked with wrong size!
  1249. fi
  1250. # end of 'hinttab.h'
  1251. fi
  1252. if test -f 'stov.c' -a "${1}" != "-c" ; then 
  1253.   echo shar: Will not clobber existing file \"'stov.c'\"
  1254. else
  1255. echo shar: Extracting \"'stov.c'\" \(2409 characters\)
  1256. sed "s/^X//" >'stov.c' <<'END_OF_FILE'
  1257. X/* stov.c -- convert string to vector
  1258. X   Copyright (C) 1989 David MacKenzie
  1259. X
  1260. X   This program is free software; you can redistribute it and/or modify
  1261. X   it under the terms of the GNU General Public License as published by
  1262. X   the Free Software Foundation; either version 1, or (at your option)
  1263. X   any later version.
  1264. X
  1265. X   This program is distributed in the hope that it will be useful,
  1266. X   but WITHOUT ANY WARRANTY; without even the implied warranty of
  1267. X   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1268. X   GNU General Public License for more details.
  1269. X
  1270. X   You should have received a copy of the GNU General Public License
  1271. X   along with this program; if not, write to the Free Software
  1272. X   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  1273. X
  1274. X#include "hint.h"
  1275. X
  1276. X/* Number of arguments between realloc's. */
  1277. X#define GRANULARITY 10
  1278. X
  1279. X/* Make an argv-like vector (string array) from string `s' (such as an
  1280. X   environment variable).  The last element of the vector is null.
  1281. X   Return a static structure with a malloc'd array of pointers into `s'.
  1282. X   Scatters nulls throughout `s'.  */
  1283. X
  1284. Xstruct args *
  1285. Xstov (s)
  1286. X     char *s;
  1287. X{
  1288. X  static struct args args;
  1289. X  int argc;
  1290. X  char **argv;
  1291. X
  1292. X  argc = 0;
  1293. X  argv = (char **) xmalloc ((unsigned) (sizeof (char *) * GRANULARITY));
  1294. X
  1295. X  for (s = strtok (s, " \t\n\r"); s; s = strtok ((char *) NULL, " \t\n\r"))
  1296. X    {
  1297. X      if (argc > 0 && argc % GRANULARITY == 0)
  1298. X    argv = (char **) xrealloc ((char *) argv,
  1299. X               (unsigned) (sizeof (char *) * (argc + GRANULARITY)));
  1300. X      argv[argc++] = s;
  1301. X    }
  1302. X  argv = (char **) xrealloc ((char *) argv,
  1303. X                 (unsigned) (sizeof (char *) * (argc + 1)));
  1304. X  argv[argc] = NULL;
  1305. X  args.argc = argc;
  1306. X  args.argv = argv;
  1307. X  return &args;
  1308. X}
  1309. X
  1310. Xstatic void
  1311. Xmemory_out ()
  1312. X{
  1313. X  fprintf (stderr, "%s: Virtual memory exhausted\n", program_name);
  1314. X  exit (1);
  1315. X}
  1316. X
  1317. X/* Allocate `n' bytes of memory dynamically, with error checking.  */
  1318. X
  1319. Xchar *
  1320. Xxmalloc (n)
  1321. X     unsigned n;
  1322. X{
  1323. X  char *p;
  1324. X
  1325. X  p = malloc (n);
  1326. X  if (p == 0)
  1327. X    memory_out ();
  1328. X  return p;
  1329. X}
  1330. X
  1331. X/* Change the size of an allocated block of memory `p' to `n' bytes,
  1332. X   with error checking.
  1333. X   If `p' is NULL, run xmalloc.
  1334. X   If `n' is 0, run free and return NULL.  */
  1335. X
  1336. Xchar *
  1337. Xxrealloc (p, n)
  1338. X     char *p;
  1339. X     unsigned n;
  1340. X{
  1341. X  if (p == 0)
  1342. X    return xmalloc (n);
  1343. X  if (n == 0)
  1344. X    {
  1345. X      free (p);
  1346. X      return 0;
  1347. X    }
  1348. X  p = realloc (p, n);
  1349. X  if (p == 0)
  1350. X    memory_out ();
  1351. X  return p;
  1352. X}
  1353. END_OF_FILE
  1354. if test 2409 -ne `wc -c <'stov.c'`; then
  1355.     echo shar: \"'stov.c'\" unpacked with wrong size!
  1356. fi
  1357. # end of 'stov.c'
  1358. fi
  1359. if test -f 'stov.h' -a "${1}" != "-c" ; then 
  1360.   echo shar: Will not clobber existing file \"'stov.h'\"
  1361. else
  1362. echo shar: Extracting \"'stov.h'\" \(880 characters\)
  1363. sed "s/^X//" >'stov.h' <<'END_OF_FILE'
  1364. X/* stov.h -- declarations for using stov function
  1365. X   Copyright (C) 1989 David MacKenzie
  1366. X
  1367. X   This program is free software; you can redistribute it and/or modify
  1368. X   it under the terms of the GNU General Public License as published by
  1369. X   the Free Software Foundation; either version 1, or (at your option)
  1370. X   any later version.
  1371. X
  1372. X   This program is distributed in the hope that it will be useful,
  1373. X   but WITHOUT ANY WARRANTY; without even the implied warranty of
  1374. X   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1375. X   GNU General Public License for more details.
  1376. X
  1377. X   You should have received a copy of the GNU General Public License
  1378. X   along with this program; if not, write to the Free Software
  1379. X   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  1380. X
  1381. X/* Structure for return value of stov. */
  1382. Xstruct args
  1383. X{
  1384. X  int argc;
  1385. X  char **argv;
  1386. X};
  1387. X
  1388. Xstruct args *stov ();
  1389. END_OF_FILE
  1390. if test 880 -ne `wc -c <'stov.h'`; then
  1391.     echo shar: \"'stov.h'\" unpacked with wrong size!
  1392. fi
  1393. # end of 'stov.h'
  1394. fi
  1395. if test -f 'str.c' -a "${1}" != "-c" ; then 
  1396.   echo shar: Will not clobber existing file \"'str.c'\"
  1397. else
  1398. echo shar: Extracting \"'str.c'\" \(2222 characters\)
  1399. sed "s/^X//" >'str.c' <<'END_OF_FILE'
  1400. X/* str.c -- string functions missing from BSD
  1401. X   Copyright (C) 1989 David MacKenzie
  1402. X
  1403. X   This program is free software; you can redistribute it and/or modify
  1404. X   it under the terms of the GNU General Public License as published by
  1405. X   the Free Software Foundation; either version 1, or (at your option)
  1406. X   any later version.
  1407. X
  1408. X   This program is distributed in the hope that it will be useful,
  1409. X   but WITHOUT ANY WARRANTY; without even the implied warranty of
  1410. X   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1411. X   GNU General Public License for more details.
  1412. X
  1413. X   You should have received a copy of the GNU General Public License
  1414. X   along with this program; if not, write to the Free Software
  1415. X   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  1416. X
  1417. X#define NULL 0
  1418. X
  1419. Xchar *index ();
  1420. X
  1421. X/* Return the length of the span of characters at the start of `string'
  1422. X   that are members of `class'.  */
  1423. X
  1424. Xint
  1425. Xstrspn (string, class)
  1426. X     char *string;
  1427. X     char *class;
  1428. X{
  1429. X  int count;
  1430. X
  1431. X  for (count = 0; string[count]; ++count)
  1432. X    if (!index (class, string[count]))
  1433. X      break;
  1434. X  return count;
  1435. X}
  1436. X
  1437. X/* Return the length of the span of characters at the start of `string'
  1438. X   that are non-members of `class'.  */
  1439. X
  1440. Xint
  1441. Xstrcspn (string, class)
  1442. X     char *string;
  1443. X     char *class;
  1444. X{
  1445. X  int count;
  1446. X
  1447. X  for (count = 0; string[count]; ++count)
  1448. X    if (index (class, string[count]))
  1449. X      break;
  1450. X  return count;
  1451. X}
  1452. X
  1453. X/* Return the next token in `string', delimited by one or more members of
  1454. X   the set `separators'.  If `string' is NULL, use the same string as in the
  1455. X   last call.  */
  1456. X
  1457. Xchar *
  1458. Xstrtok (string, separators)
  1459. X     char *string;
  1460. X     char *separators;
  1461. X{
  1462. X  static char *pos = NULL;    /* Current location in the string. */
  1463. X  int token_length;
  1464. X
  1465. X  if (string)
  1466. X    pos = string;
  1467. X  pos += strspn (pos, separators);    /* Skip initial separators. */
  1468. X  token_length = strcspn (pos, separators);    /* Find token length. */
  1469. X  if (token_length == 0)
  1470. X    return NULL;        /* No more tokens; pos is on a 0. */
  1471. X  separators = pos;        /* Re-use separators to save start of token. */
  1472. X  pos += token_length;        /* Move onto the 0. */
  1473. X  if (*pos)            /* If not the last token, */
  1474. X    *pos++ = 0;            /* null terminate the token. */
  1475. X  return separators;
  1476. X}
  1477. END_OF_FILE
  1478. if test 2222 -ne `wc -c <'str.c'`; then
  1479.     echo shar: \"'str.c'\" unpacked with wrong size!
  1480. fi
  1481. # end of 'str.c'
  1482. fi
  1483. if test -f 'user.c' -a "${1}" != "-c" ; then 
  1484.   echo shar: Will not clobber existing file \"'user.c'\"
  1485. else
  1486. echo shar: Extracting \"'user.c'\" \(1906 characters\)
  1487. sed "s/^X//" >'user.c' <<'END_OF_FILE'
  1488. X/* user.c -- functions dealing with logins
  1489. X   Copyright (C) 1989 David MacKenzie
  1490. X
  1491. X   This program is free software; you can redistribute it and/or modify
  1492. X   it under the terms of the GNU General Public License as published by
  1493. X   the Free Software Foundation; either version 1, or (at your option)
  1494. X   any later version.
  1495. X
  1496. X   This program is distributed in the hope that it will be useful,
  1497. X   but WITHOUT ANY WARRANTY; without even the implied warranty of
  1498. X   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1499. X   GNU General Public License for more details.
  1500. X
  1501. X   You should have received a copy of the GNU General Public License
  1502. X   along with this program; if not, write to the Free Software
  1503. X   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
  1504. X
  1505. X#include "hint.h"
  1506. X#include <utmp.h>
  1507. X
  1508. X/* Add all ttys where `user' is logged on to the list of ttys to hint.
  1509. X   Return the number of times `user' is logged on.  */
  1510. X
  1511. Xint
  1512. Xadduser (user)
  1513. X     char *user;
  1514. X{
  1515. X  struct utmp ut;
  1516. X  int nfound;            /* Number of times `user' is logged on. */
  1517. X  int fd;
  1518. X
  1519. X  fd = open ("/etc/utmp", O_RDONLY);
  1520. X  if (fd == -1)
  1521. X    pfatal ("/etc/utmp");
  1522. X
  1523. X  nfound = 0;
  1524. X  while (read (fd, &ut, sizeof (struct utmp)) > 0)
  1525. X    nfound += addmatch (user, &ut);
  1526. X
  1527. X  close (fd);
  1528. X  return nfound;
  1529. X}
  1530. X
  1531. X/* If the name field in `utp' matches `user' and the tty is hint y,
  1532. X     add the `utp' tty field to the list of ttys to hint and return 1;
  1533. X   else,
  1534. X     return 0.  */
  1535. X
  1536. Xint
  1537. Xaddmatch (user, utp)
  1538. X     char *user;
  1539. X     struct utmp *utp;
  1540. X{
  1541. X  char temp_line[30];        /* 30 is random number > max. ut_line size. */
  1542. X
  1543. X  /* Make sure it's a valid entry. */
  1544. X  if (*utp->ut_name == 0)
  1545. X    return 0;
  1546. X
  1547. X  if (!strncmp (user, utp->ut_name, sizeof (utp->ut_name)))
  1548. X    {
  1549. X      strncpy (temp_line, utp->ut_line, sizeof (utp->ut_line));
  1550. X      temp_line[sizeof (utp->ut_line)] = 0;
  1551. X      addtty (user, temp_line);
  1552. X      return 1;
  1553. X    }
  1554. X  else
  1555. X    return 0;
  1556. X}
  1557. END_OF_FILE
  1558. if test 1906 -ne `wc -c <'user.c'`; then
  1559.     echo shar: \"'user.c'\" unpacked with wrong size!
  1560. fi
  1561. # end of 'user.c'
  1562. fi
  1563. if test -f 'hall.sh' -a "${1}" != "-c" ; then 
  1564.   echo shar: Will not clobber existing file \"'hall.sh'\"
  1565. else
  1566. echo shar: Extracting \"'hall.sh'\" \(1009 characters\)
  1567. sed "s/^X//" >'hall.sh' <<'END_OF_FILE'
  1568. X#!/bin/sh
  1569. X#  hall -- hint all users logged in
  1570. X#  Copyright (C) 1989 David MacKenzie
  1571. X#
  1572. X#  This program is free software; you can redistribute it and/or modify
  1573. X#  it under the terms of the GNU General Public License as published by
  1574. X#  the Free Software Foundation; either version 1, or (at your option)
  1575. X#  any later version.
  1576. X#
  1577. X#  This program is distributed in the hope that it will be useful,
  1578. X#  but WITHOUT ANY WARRANTY; without even the implied warranty of
  1579. X#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1580. X#  GNU General Public License for more details.
  1581. X#
  1582. X#  You should have received a copy of the GNU General Public License
  1583. X#  along with this program; if not, write to the Free Software
  1584. X#  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1585. X
  1586. X# Usage: hall [message]
  1587. X# David MacKenzie
  1588. X# Latest revision: 08/23/89
  1589. X
  1590. Xecho 'Making list of everyone logged on . . .'
  1591. Xusers=`who|awk '{ if (NR > 1) printf ","; printf "%s", $1 }'`
  1592. Xif [ $# -eq 0 ]
  1593. Xthen
  1594. X  hint $users
  1595. Xelse
  1596. X  hint $users "$@"
  1597. Xfi
  1598. END_OF_FILE
  1599. if test 1009 -ne `wc -c <'hall.sh'`; then
  1600.     echo shar: \"'hall.sh'\" unpacked with wrong size!
  1601. fi
  1602. chmod +x 'hall.sh'
  1603. # end of 'hall.sh'
  1604. fi
  1605. echo shar: End of archive 1 \(of 2\).
  1606. cp /dev/null ark1isdone
  1607. MISSING=""
  1608. for I in 1 2 ; do
  1609.     if test ! -f ark${I}isdone ; then
  1610.     MISSING="${MISSING} ${I}"
  1611.     fi
  1612. done
  1613. if test "${MISSING}" = "" ; then
  1614.     echo You have unpacked both archives.
  1615.     rm -f ark[1-9]isdone
  1616. else
  1617.     echo You still need to unpack the following archives:
  1618.     echo "        " ${MISSING}
  1619. fi
  1620. ##  End of shell archive.
  1621. exit 0
  1622.  
  1623.